(*****************************************************************************
 * Delphi Plug-in Framework (DPF)
 * Copyright (C) 2006-2007 Tao Yuan
 *
 * The contents of this file are subject to the Mozilla Public License
 * Version 1.1 (the "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the
 * License at http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
 * the specific language governing rights and limitations under the License.                                                               }
 *
 * The Initial Developer of the Original Code is Tao Yuan. Portions created by
 * Tao Yuan are Copyright (C) Tao Yuan (taoy.cn att gmail dott com)
 * All rights reserved.
 *****************************************************************************)
unit RDManifestParser;

interface

uses
  Classes,
  Rcl,
  RDModel, RDManifestHandler, RDManifestInfoHandler;

type
  TRdManifestParser = class(TObject)
  private

    class function getDtdEntityResolver: IEntityResolver;
    class function loadPluginDtd(version: string): TStream;
  protected

    entityResolver: IEntityResolver;
  public
    constructor Create(isValidating : Boolean);
    destructor Destroy; override;
    function parseManifest(url: string): TModelPluginManifest;
    function parseManifestInfo(url: string): TModelManifestInfo;
  end;

  TRdEntityResolver = class(TInterfacedObject, IEntityResolver)
  protected
    function resolveEntity(const publicId, systemId : SAXString): IInputSource;
  end;

implementation

uses
  SysUtils;

var
  PLUGIN_DTD_0_2,
  PLUGIN_DTD_0_3,
  PLUGIN_DTD_0_4,
  PLUGIN_DTD_0_5: TStream;
//  log: Rcl.TLogger;

constructor TRdManifestParser.Create(isValidating : Boolean);
begin
  inherited Create;

  if isValidating then
    entityResolver := getDtdEntityResolver
  else
    entityResolver := nil;  

end;

destructor TRdManifestParser.Destroy;
begin
  inherited;
end;

class function TRdManifestParser.getDtdEntityResolver: IEntityResolver;
begin
  Result := TRdEntityResolver.Create;
end;

class function TRdManifestParser.loadPluginDtd(version: string): TStream;
begin
  Result := TFileStream.Create('plugin_' + version + '.dtd', fmOpenRead);
//  try
//    try
//    except
////      log.error('can''t read plug-in DTD file of version ' + version); //$NON-NLS-1$
//    end;
//  finally
//
//  end;
end;

function TRdManifestParser.parseManifest(url: string): TModelPluginManifest;
var
  XMLReader: IXMLReader;
  LHandler: TBaManifestHandler;
begin
  XMLReader := TXMLReaderFactory.GetReader;
  try
    XMLReader.EntityResolver := entityResolver;
    LHandler := TBaManifestHandler.Create(entityResolver);
    XMLReader.ContentHandler := LHandler;
  //  XMLReader.Parse(TInputSourceHelp.CreateInputSource(url));
    XMLReader.Parse(url);
    Result := LHandler.getResult;
  finally
    XMLReader := nil;
  end;
//  XMLReader.ContentHandler := nil;
end;

function TRdManifestParser.parseManifestInfo(url: string): TModelManifestInfo;
var
  XMLReader: IXMLReader;
  LHandler: TManifestInfoHandler;
begin
  XMLReader := TXMLReaderFactory.GetReader;
  try
    XMLReader.EntityResolver := entityResolver;
    LHandler := TManifestInfoHandler.Create(entityResolver);
    XMLReader.ContentHandler := LHandler;
  //  XMLReader.Parse(TInputSourceHelp.CreateInputSource(url));
    XMLReader.Parse(url);
    Result := LHandler.getResult;
  finally
    XMLReader := nil;
  end;
//  XMLReader.ContentHandler := nil;
end;

function TRdEntityResolver.resolveEntity(const publicId, systemId : SAXString):
    IInputSource;
begin
  Result := nil;
  //log.debug("publicId=" + publicId + ", systemId=" + systemId);
  if (publicId = '') then
      Exit;

  if Rcl.Str.IsEqual(publicId, '-//DPF//Delphi Plug-in Manifest 0.5') //$NON-NLS-1$
          and (PLUGIN_DTD_0_5 <> nil) then
  begin
    Result := TStreamInputSource.Create(PLUGIN_DTD_0_5);
    Exit;
  end;

  if Rcl.Str.IsEqual(publicId, '-//DPF//Delphi Plug-in Manifest 0.4') //$NON-NLS-1$
          and (PLUGIN_DTD_0_4 <> nil) then
  begin
    Result := TStreamInputSource.Create(PLUGIN_DTD_0_4);
    Exit;
  end;

  if Rcl.Str.IsEqual(publicId, '-//DPF//Delphi Plug-in Manifest 0.3') //$NON-NLS-1$
          and (PLUGIN_DTD_0_3 <> nil) then
  begin
    Result := TStreamInputSource.Create(PLUGIN_DTD_0_3);
    Exit;
  end;

  if Rcl.Str.IsEqual(publicId, '-//DPF//Delphi Plug-in Manifest 0.2') //$NON-NLS-1$
          and (PLUGIN_DTD_0_2 <> nil) then
  begin
    Result := TStreamInputSource.Create(PLUGIN_DTD_0_2);
    Exit;
  end;
end;

initialization
//  PLUGIN_DTD_0_2 := TRdManifestParser.loadPluginDtd('0_2');
//  PLUGIN_DTD_0_3 := TRdManifestParser.loadPluginDtd('0_3');
//  PLUGIN_DTD_0_4 := TRdManifestParser.loadPluginDtd('0_4');
//  PLUGIN_DTD_0_5 := TRdManifestParser.loadPluginDtd('0_5');

finalization
//  FreeAndNil(PLUGIN_DTD_0_2);
//  FreeAndNil(PLUGIN_DTD_0_3);
//  FreeAndNil(PLUGIN_DTD_0_4);
//  FreeAndNil(PLUGIN_DTD_0_5);
  
end.
